package thread;

import lombok.extern.slf4j.Slf4j;

/**
 * 两阶段终止的案例代码。
 *  注意：两阶段提交在，捕获【InterruptedException】异常时，会再调用【interrupt】方法打断当前线程。
 *  这是为了彻底结束当前线程。
 *  在我们的项目中。所有使用了【redis分布式锁】的地方，解锁，都是这样操作的。会在捕获的异常中再次打断当前线程。
 *
 *  在我们项目中：只要有【InterruptedException】异常的地方，都会在catch模块中【重新调用【interrupt】方法】打断它。
 *      这是为了使得线程被正确的打断。（即使这个打断逻辑不是我们自己写的）。
 */
@Slf4j(topic = "c.TwoPhaseTerminationTest")
public class TwoPhaseTerminationTest {
    public static void main(String[] args) throws InterruptedException {
        TwoPhaseTermination twoPhaseTermination = new TwoPhaseTermination();
        twoPhaseTermination.start();

        Thread.sleep(3500);
        twoPhaseTermination.stop();
    }
}

@Slf4j(topic = "c.TwoPhaseTermination")
class TwoPhaseTermination{
    private Thread monitor;

    //启动监控线程
    public void start(){
        monitor = new Thread(()->{
            while (true){
                //获取当前线程
                Thread current = Thread.currentThread();
                //情况1：（在非阻塞状态下被打断）判断当前线程是否需要中断。
                //注意：这个方法【isInterrupted】不会清除打断标记。这个方法【interrupted】会清除打断标记。
                //记得注意这个不同点。
                if(current.isInterrupted()){
                    log.debug("当前线程被打断了，中断自己的循环");
                    break;
                }
                try{
                    //情况2：在阻塞状态下，被打断，（抛出该异常，如果程序破获了该异常，则激活当前线程）。
                    Thread.sleep(1000);
                    log.debug("执行监控记录");
                }catch (InterruptedException e){
                    // 用户捕获了该异常，所以这个线程被激活了，并且【打断状态为false】。
                    e.printStackTrace();
                    //重新打断该线程，后续程序进来的时候，才可以正常退出。
                    current.interrupt();
                }
            }
        });
    }

    //停止监控线程
    public void stop(){
        monitor.interrupt();
    }
}
